package com.warrior.gatherclient.service.impl;

import com.warrior.gatherclient.grpc.Messages;
import com.warrior.gatherclient.util.CommonUtil;
import com.warrior.gatherclient.util.DateUtil;
import com.warrior.gatherclient.service.OperatingSystemService;
import com.warrior.gatherclient.service.SystemInfoService;
import com.warrior.gathercommon.constants.CommonStatus;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import oshi.SystemInfo;
import oshi.software.os.InternetProtocolStats;
import oshi.software.os.OperatingSystem;

import java.util.Date;

/**
 * @ClassName OperatingSystemServiceImpl.java
 * @Author xujian
 * @Description
 * @CreateTime 2020年12月11日 15:20:00
 */
@Slf4j
@Service
public class OperatingSystemServiceImpl implements OperatingSystemService {

    @Autowired
    private SystemInfoService systemInfoService;

    @Override
    public String getServiceKey() {
        return CommonStatus.CONSTANT_OPERATIONG_SYSTEM;
    }

    /**
     * @Author xujian
     * @Description 采集tcpv4相关连接数据
     * @Date 14:11 2020/12/30
     * @Param [systemInfo, messages]
     * @return void
     **/
    private void addTcpv4(SystemInfo systemInfo, Messages.Builder messages) {
        InternetProtocolStats.TcpStats tcPv4Stats = systemInfo.getOperatingSystem().getInternetProtocolStats().getTCPv4Stats();
        Messages.Metric.Builder builder = Messages.Metric.newBuilder();
        builder.setMetricName(CommonStatus.CONSTANT_OPERATIONG_SYSTEM_TCPV4_ESTABLISHED);
        builder.setMetricVaule(String.valueOf(tcPv4Stats.getConnectionsEstablished()));
        messages.addMetrics(builder);

        Messages.Metric.Builder actBuilder = Messages.Metric.newBuilder();
        actBuilder.setMetricName(CommonStatus.CONSTANT_OPERATIONG_SYSTEM_TCPV4_ACTIVE);
        actBuilder.setMetricVaule(String.valueOf(tcPv4Stats.getConnectionsActive()));
        messages.addMetrics(actBuilder);

        Messages.Metric.Builder passBuilder = Messages.Metric.newBuilder();
        passBuilder.setMetricName(CommonStatus.CONSTANT_OPERATIONG_SYSTEM_TCPV4_PASSIVE);
        passBuilder.setMetricVaule(String.valueOf(tcPv4Stats.getConnectionsPassive()));
        messages.addMetrics(passBuilder);

        Messages.Metric.Builder failBuilder = Messages.Metric.newBuilder();
        failBuilder.setMetricName(CommonStatus.CONSTANT_OPERATIONG_SYSTEM_TCPV4_FAILURES);
        failBuilder.setMetricVaule(String.valueOf(tcPv4Stats.getConnectionFailures()));
        messages.addMetrics(failBuilder);

        Messages.Metric.Builder resetBuilder = Messages.Metric.newBuilder();
        resetBuilder.setMetricName(CommonStatus.CONSTANT_OPERATIONG_SYSTEM_TCPV4_RESET);
        resetBuilder.setMetricVaule(String.valueOf(tcPv4Stats.getConnectionsReset()));
        messages.addMetrics(resetBuilder);

        Messages.Metric.Builder sentBuilder = Messages.Metric.newBuilder();
        sentBuilder.setMetricName(CommonStatus.CONSTANT_OPERATIONG_SYSTEM_TCPV4_SENT);
        sentBuilder.setMetricVaule(String.valueOf(tcPv4Stats.getSegmentsSent()));
        messages.addMetrics(sentBuilder);

        Messages.Metric.Builder receivedBuilder = Messages.Metric.newBuilder();
        receivedBuilder.setMetricName(CommonStatus.CONSTANT_OPERATIONG_SYSTEM_TCPV4_RECEIVED);
        receivedBuilder.setMetricVaule(String.valueOf(tcPv4Stats.getSegmentsReceived()));
        messages.addMetrics(receivedBuilder);

        Messages.Metric.Builder retransmittedBuilder = Messages.Metric.newBuilder();
        retransmittedBuilder.setMetricName(CommonStatus.CONSTANT_OPERATIONG_SYSTEM_TCPV4_RETRANSMITTED);
        retransmittedBuilder.setMetricVaule(String.valueOf(tcPv4Stats.getSegmentsRetransmitted()));
        messages.addMetrics(retransmittedBuilder);

        Messages.Metric.Builder inerrorsBuilder = Messages.Metric.newBuilder();
        inerrorsBuilder.setMetricName(CommonStatus.CONSTANT_OPERATIONG_SYSTEM_TCPV4_INERRORS);
        inerrorsBuilder.setMetricVaule(String.valueOf(tcPv4Stats.getInErrors()));
        messages.addMetrics(inerrorsBuilder);

        Messages.Metric.Builder outresetsBuilder = Messages.Metric.newBuilder();
        outresetsBuilder.setMetricName(CommonStatus.CONSTANT_OPERATIONG_SYSTEM_TCPV4_OUTRESETS);
        outresetsBuilder.setMetricVaule(String.valueOf(tcPv4Stats.getOutResets()));
        messages.addMetrics(outresetsBuilder);
    }

    /**
     * @Author xujian
     * @Description 系统运行时间（单位s）
     * @Date 14:15 2020/12/30
     * @Param [systemInfo, messages]
     * @return void
     **/
    private void addSystemUptime(SystemInfo systemInfo, Messages.Builder messages) {
        OperatingSystem operatingSystem = systemInfo.getOperatingSystem();
        long systemUptime = operatingSystem.getSystemUptime();
        Messages.Metric.Builder builder = Messages.Metric.newBuilder();
        builder.setMetricName(CommonStatus.CONSTANT_OPERATIONG_SYSTEM_SYSTEMUPTIME);
        builder.setMetricVaule(String.valueOf(systemUptime));
        messages.addMetrics(builder);
    }

    /**
     * @Author xujian
     * @Description 系统启动时间
     * @Date 14:16 2020/12/30
     * @Param [systemInfo, messages]
     * @return void
     **/
    private void addSystemBootTime(SystemInfo systemInfo, Messages.Builder messages) {
        OperatingSystem operatingSystem = systemInfo.getOperatingSystem();
        long systemBootTime = operatingSystem.getSystemBootTime();
        String bootTime = DateUtil.covertDateToString(new Date(systemBootTime * 1000L), null);
        Messages.Metric.Builder builder = Messages.Metric.newBuilder();
        builder.setMetricName(CommonStatus.CONSTANT_OPERATIONG_SYSTEM_BOOTTIME);
        builder.setMetricVaule(String.valueOf(bootTime));
        messages.addMetrics(builder);
    }

    @Override
    public Messages.Builder execute() {
        SystemInfo systemInfo = systemInfoService.getSystemInfo();
        OperatingSystem operatingSystem = systemInfo.getOperatingSystem();

        Messages.Builder messages = CommonUtil.initMessage(CommonStatus.CONSTANT_OPERATIONG_SYSTEM);

        //操作系统名称
        String operating = operatingSystem.toString();
        Messages.Metric.Builder operatingSystemBuilder = Messages.Metric.newBuilder();
        operatingSystemBuilder.setMetricName(CommonStatus.CONSTANT_OPERATIONG_OPERATING);
        operatingSystemBuilder.setMetricVaule(operating);
        messages.addMetrics(operatingSystemBuilder.build());

        //进程数
        int processCount = operatingSystem.getProcessCount();
        Messages.Metric.Builder builder = Messages.Metric.newBuilder();
        builder.setMetricName(CommonStatus.CONSTANT_OPERATIONG_SYSTEM_PROCESS_COUNT);
        builder.setMetricVaule(String.valueOf(processCount));
        messages.addMetrics(builder);

        addTcpv4(systemInfo, messages);
        addSystemUptime(systemInfo, messages);
        addSystemBootTime(systemInfo, messages);

        return messages;
    }
}
